package com.ymatou.iapi.refund.parameter;

import java.math.BigDecimal;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

public class ProductRefundAmountInfo {
	   /**
     * 退款商品规格Id
     */
    private String catalogId;
    /**
     * 退款数量
     */
    private int refundQuantity;
    /**
     * 用户申请的退款金额
     */
    private BigDecimal applyRefundAmount;
    /**
     * 实际退还商品金额，不包括运费
     */
    private BigDecimal realRefundProductAmount;
    /**
     * 实际退还运费
     */
    private BigDecimal realRefundFreight;
    /**
     * 最大可退商品金额
     */
    private BigDecimal maxRefundableProductAmount;
    /**
     * 最大可退商品运费
     */
    private BigDecimal maxRefundableFreight;

    public BigDecimal getApplyRefundAmount() {
        return applyRefundAmount;
    }

    public void setApplyRefundAmount(BigDecimal applyRefundAmount) {
        this.applyRefundAmount = applyRefundAmount;
    }

    public BigDecimal getRealRefundProductAmount() {
        return realRefundProductAmount;
    }

    public void setRealRefundProductAmount(BigDecimal realRefundProductAmount) {
        this.realRefundProductAmount = realRefundProductAmount;
    }

    public BigDecimal getRealRefundFreight() {
        return realRefundFreight;
    }

    public void setRealRefundFreight(BigDecimal realRefundFreight) {
        this.realRefundFreight = realRefundFreight;
    }

    public BigDecimal getMaxRefundableProductAmount() {
        return maxRefundableProductAmount;
    }

    public void setMaxRefundableProductAmount(BigDecimal maxRefundableProductAmount) {
        this.maxRefundableProductAmount = maxRefundableProductAmount;
    }

    public BigDecimal getMaxRefundableFreight() {
        return maxRefundableFreight;
    }

    public void setMaxRefundableFreight(BigDecimal maxRefundableFreight) {
        this.maxRefundableFreight = maxRefundableFreight;
    }

    public String getCatalogId() {
        return catalogId;
    }

    public void setCatalogId(String catalogId) {
        this.catalogId = catalogId;
    }

    public int getRefundQuantity() {
        return refundQuantity;
    }

    public void setRefundQuantity(int refundQuantity) {
        this.refundQuantity = refundQuantity;
    }

    public ProductRefundAmountInfo() {
    }

    /**
     * 计算商品最大可退金额
     *
     * @return
     */
    public BigDecimal getMaxRefundableAmount() {
        return this.maxRefundableProductAmount.add(this.maxRefundableFreight);
    }

    public static ProductRefundAmountInfo of(String catalogId, int refundQuantity,
                                             BigDecimal applyRefundAmount,
                                             BigDecimal maxRefundableProductAmount,
                                             BigDecimal maxRefundableFreight) {
//        if (catalogId == null || applyRefundAmount == null || maxRefundableProductAmount == null || maxRefundableFreight == null) {
//            throw new BizException("args is not null");
//        }
        ProductRefundAmountInfo amountInfo = new ProductRefundAmountInfo();
        amountInfo.setCatalogId(catalogId);
        amountInfo.setRefundQuantity(refundQuantity);
        amountInfo.setApplyRefundAmount(applyRefundAmount);
        amountInfo.setMaxRefundableFreight(maxRefundableFreight);
        amountInfo.setMaxRefundableProductAmount(maxRefundableProductAmount);

        BigDecimal realProductRefundAmount, realRefundFreight;
        if (applyRefundAmount.compareTo(maxRefundableProductAmount) >= 0) {
            realProductRefundAmount = maxRefundableProductAmount;
            realRefundFreight = applyRefundAmount.subtract(maxRefundableProductAmount);
        } else {
            realProductRefundAmount = applyRefundAmount;
            realRefundFreight = new BigDecimal("0");
        }
        amountInfo.setRealRefundFreight(realRefundFreight);
        amountInfo.setRealRefundProductAmount(realProductRefundAmount);
        return amountInfo;
    }

//    public static List<ProductRefundAmountInfo> ofList(SingleOrderInfo orderInfo) {
//    //    Assert.notNull(orderInfo, "orderInfo is null");
//
//        List<ProductRefundAmountInfo> productRefundAmountInfos = Lists.newArrayList();
//        for (OrderItemInfo orderItemInfo : orderInfo.getOrderItemList()) {
//            productRefundAmountInfos.add(
//                    ProductRefundAmountInfo.of(orderItemInfo.getCatalogId(),
//                            orderItemInfo.getAmount(),
//                            orderItemInfo.getMaxCanRefundProAmount().add(NumberUtils.nullToZero(orderItemInfo.getFreight())),
//                            orderItemInfo.getMaxCanRefundProAmount(),
//                            NumberUtils.nullToZero(orderItemInfo.getFreight())));
//        }
//        return productRefundAmountInfos;
//    }

    public static List<ProductRefundAmountInfo> calculate(BigDecimal applyRefundTotalAmount, List<ProductRefundAmountInfo> productRefundAmountInfos) {
        if (CollectionUtils.isEmpty(productRefundAmountInfos)) {
            return productRefundAmountInfos;
        }
        BigDecimal maxRefundableProductTotalAmount = calcMaxRefundableProductTotalAmount(productRefundAmountInfos);
        BigDecimal realRefundFreight = applyRefundTotalAmount.subtract(maxRefundableProductTotalAmount);
        if (realRefundFreight.compareTo(BigDecimal.ZERO) < 0) {
            realRefundFreight = BigDecimal.ZERO;
        }
        List<ProductRefundAmountInfo> results = Lists.newArrayList();
        if (applyRefundTotalAmount.compareTo(maxRefundableProductTotalAmount) >= 0) {
            for (ProductRefundAmountInfo productRefundAmountInfo : productRefundAmountInfos) {
                BigDecimal perApplyRefundAmount = productRefundAmountInfo.getMaxRefundableProductAmount();
                //表示运费放在此商品上
                if (productRefundAmountInfo.getMaxRefundableFreight().compareTo(BigDecimal.ZERO) > 0) {
                    perApplyRefundAmount = perApplyRefundAmount.add(realRefundFreight);
                }
                results.add(ProductRefundAmountInfo.of(productRefundAmountInfo.getCatalogId(),
                        productRefundAmountInfo.refundQuantity,
                        perApplyRefundAmount,
                        productRefundAmountInfo.getMaxRefundableProductAmount(),
                        productRefundAmountInfo.getMaxRefundableFreight()));
            }
        } else {
            //接比例计算退款金额
            int count = 0;
            BigDecimal calculatedApplyRefundTotalAmount = BigDecimal.ZERO;
            for (ProductRefundAmountInfo productRefundAmountInfo : productRefundAmountInfos) {
                BigDecimal perApplyRefundAmount;
                count += 1;
                if (count < productRefundAmountInfos.size()) {
                    perApplyRefundAmount = productRefundAmountInfo.getMaxRefundableProductAmount()
                            .divide(maxRefundableProductTotalAmount, 2, RoundingMode.DOWN)
                            .multiply(applyRefundTotalAmount);
                    if (perApplyRefundAmount.scale() > 2) {
                        perApplyRefundAmount = perApplyRefundAmount.setScale(2, RoundingMode.DOWN);
                    }
                    calculatedApplyRefundTotalAmount = calculatedApplyRefundTotalAmount.add(perApplyRefundAmount);
                } else {
                    perApplyRefundAmount = applyRefundTotalAmount.subtract(calculatedApplyRefundTotalAmount);
                }

                results.add(ProductRefundAmountInfo.of(productRefundAmountInfo.getCatalogId(),
                        productRefundAmountInfo.refundQuantity,
                        perApplyRefundAmount,
                        productRefundAmountInfo.getMaxRefundableProductAmount(),
                        productRefundAmountInfo.getMaxRefundableFreight()));
            }
        }
        return results;
    }

    public static BigDecimal calcMaxRefundableProductTotalAmount(List<ProductRefundAmountInfo> productRefundAmountInfos) {
        if (CollectionUtils.isEmpty(productRefundAmountInfos)) {
            return BigDecimal.valueOf(0L);
        }
        BigDecimal total = BigDecimal.valueOf(0L);
        for (ProductRefundAmountInfo productRefundAmountInfo : productRefundAmountInfos) {
            total = total.add(productRefundAmountInfo.getMaxRefundableProductAmount());
        }
        return total;
    }

    public static BigDecimal calcMaxRefundableFreight(List<ProductRefundAmountInfo> productRefundAmountInfos) {
        if (CollectionUtils.isEmpty(productRefundAmountInfos)) {
            return BigDecimal.valueOf(0L);
        }
        BigDecimal freight = BigDecimal.valueOf(0L);
        for (ProductRefundAmountInfo productRefundAmountInfo : productRefundAmountInfos) {
            freight = freight.add(productRefundAmountInfo.getMaxRefundableFreight());
        }
        return freight;
    }

    public static BigDecimal calcMaxRefundableTotalAmount(List<ProductRefundAmountInfo> productRefundAmountInfos) {
        return calcMaxRefundableProductTotalAmount(productRefundAmountInfos).add(calcMaxRefundableFreight(productRefundAmountInfos));
    }

}
